iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
Software Development

用Canvas打造自己的遊樂場系列 第 28

[Day28]用Canvas打造自己的遊樂場-labyrinth 收尾

  • 分享至 

  • xImage
  •  

今天要來把迷宮遊戲做個收尾,其實也就檢查一下有沒有哪裡有問題,那因為後來覺得55塊磚的範圍還有有點大,所以改成33.
另外就是在checkMapBrick有寫錯,所以有穿牆的bug.對此做了修正
那這邊做為結尾,附上整餓由戲的整段code

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Second Game</title>
    <meta name="description" content="第三個遊戲">
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
</head>

<body>
    <canvas id="playground" width="120" height="120"></canvas>
    <script>
        // 地圖設定
        const MAP_BRICKS = 40;
        const BRICK_SPACING = 1;
        const BRICK_COLS = 33;
        const BRICK_ROWS = 22;

        // 視線範圍
        var map_x = 0.0;
        var map_y = 0.0;

        // 移動速度
        const MOVE_SPEED = 2.5;

        // 玩家
        var player_x;
        var player_y;
        const PLAYER_R = 5;
        const KEY_LEFT_ARROW = 37;
        const KEY_UP_ARROW = 38;
        const KEY_RIGHT_ARROW = 39;
        const KEY_DOWN_ARROW = 40;
        var keyLeft = false;
        var keyRight = false;
        var keyTop = false;
        var keyDown = false;

        var map = [
            0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1,
            1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1,
            1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1,
            1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1,
            1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1,
            1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1,
            1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1,
            1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,
            1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1,
            1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
            1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,
            1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
            1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
            1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
            1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1,
            1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1,
            1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
            1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1,
            1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1,
            1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

        ];

        window.onload = () => {
            canvas = document.getElementById('playground');
            canvasContext = canvas.getContext('2d');

            initInput();

            //一秒更新幾次畫面
            var timesPerSec = 30;
            setInterval(drawAll, 1000 / timesPerSec);

            resetPlayer();
        }

        // 負責更新畫面
        drawAll = () => {
            console.log(keyTop,keyDown,keyLeft,keyRight);
            move();
            draw();
        }

        // 負責畫畫
        draw = () => {
            // background
            drawRectangle(0, 0, canvas.width, canvas.height, 'black');

            canvasContext.save();

            canvasContext.translate(-map_x, -map_y);

            // 小畫面的地圖
            drawMapInShadow();

            drawCircle(player_x, player_y, PLAYER_R, 'red');

            canvasContext.restore();
        }

        // 負責處理動作
        move = () => {
            map_x = player_x - canvas.width / 2;
            map_y = player_y - canvas.height / 2;

            playerMove();
        }

        // 小畫面地圖
        drawMapInShadow = () => {
            var mapLeftCol = Math.floor(map_x / MAP_BRICKS);
            var mapTopRow = Math.floor(map_y / MAP_BRICKS);

            var colFitOnScreen = Math.floor(canvas.width / MAP_BRICKS);
            var rowFitOnScreen = Math.floor(canvas.height / MAP_BRICKS);

            var mapRightCol = mapLeftCol + colFitOnScreen + 1;
            var mapBottomRow = mapTopRow + rowFitOnScreen + 1;

            for (var col = mapLeftCol; col < mapRightCol; col++) {
                for (var row = mapTopRow; row < mapBottomRow; row++) {
                    if (mapBrick(col, row)) {
                        drawRectangle(
                            col * MAP_BRICKS,
                            row * MAP_BRICKS,
                            MAP_BRICKS - BRICK_SPACING,
                            MAP_BRICKS - BRICK_SPACING,
                            'gray'
                        )
                    }
                }
            }
        }

        brickToIndex = (col, row) => {
            return (col + BRICK_COLS * row);
        }

        mapBrick = (col, row) => {
            var index = brickToIndex(col, row);
            return (map[index] == 1);
        }

        resetPlayer = () => {
            player_x = 660;
            player_y = 440;
        }

        initInput = () => {
            document.addEventListener("keydown", keyPressed);
            document.addEventListener("keyup", keyReleased);
        }

        keyPressed = (evt) => {
            setKeyState(evt.keyCode, true);
            evt.preventDefault();
        }

        keyReleased = (evt) => {
            setKeyState(evt.keyCode, false);
        }

        setKeyState = (key, to) => {
            if (key == KEY_LEFT_ARROW) {
                keyLeft = to;
            }
            if (key == KEY_RIGHT_ARROW) {
                keyRight = to;
            }
            if (key == KEY_UP_ARROW) {
                keyTop = to;
            }
            if (key == KEY_DOWN_ARROW) {
                keyDown = to;
            }
        }

        playerMove = () => {
            var next_x = player_x;
            var next_y = player_y;

            if (keyLeft) {
                next_x -= MOVE_SPEED;
            }
            if (keyRight) {
                next_x += MOVE_SPEED;
            }
            if (keyTop) {
                next_y -= MOVE_SPEED;
            }
            if (keyDown) {
                next_y += MOVE_SPEED;
            }

            if (checkMapBrick(next_x, next_y) == false) {
                player_x = next_x;
                player_y = next_y;
            }
        }

        checkMapBrick = (x, y) => {
            var col = Math.floor(x / MAP_BRICKS);
            var row = Math.floor(y / MAP_BRICKS);
            
            if (col < 0 || col >= MAP_BRICKS || row < 0 || row >= MAP_BRICKS) {
                return false;
            }

            var index = brickToIndex(col, row);
        
            return (map[index] == 1);
        }

        // 矩形元件
        drawRectangle = (topLeftX, topLeftY, boxWidth, boxHeight, color) => {
            canvasContext.fillStyle = color;
            canvasContext.fillRect(topLeftX, topLeftY, boxWidth, boxHeight);
        }

        // 圓形元件
        drawCircle = (centerX, centerY, r, color) => {
            canvasContext.fillStyle = color;
            canvasContext.beginPath();
            canvasContext.arc(centerX, centerY, r, 0, Math.PI * 2);
            canvasContext.fill();
        }

        // 畫線
        drawLine = (beginX, beginY, endX, endY, color) => {
            canvasContext.strokeStyle = color;
            canvasContext.beginPath();
            canvasContext.moveTo(beginX, beginY);
            canvasContext.lineTo(endX, endY);
            canvasContext.stroke();
        }

        // 畫生命
        drawLife = (lifeX, lifeY, size, color) => {
            canvasContext.fillStyle = color;
            canvasContext.beginPath();
            canvasContext.arc(lifeX + size / 4, lifeY + size / 4, size / 4, Math.PI * 1, Math.PI * 0);
            canvasContext.arc(lifeX + size * 3 / 4, lifeY + size / 4, size / 4, Math.PI * 1, Math.PI * 0);
            canvasContext.moveTo(lifeX + size, lifeY + size / 4);
            canvasContext.lineTo(lifeX + size / 2, lifeY + size);
            canvasContext.lineTo(lifeX, lifeY + size / 4);
            canvasContext.fill();
        }

        // 畫出生命
        showLife = (num) => {
            for (let life_count = 0; life_count < num; life_count++) {
                drawLife(LIFE_SIZE * life_count, 0, LIFE_SIZE, 'red');
            }
        }

    </script>
</body>

</html>

上一篇
[Day27]用Canvas打造自己的遊樂場-labyrinth 鍵盤控制角色
下一篇
[Day29]用Canvas打造自己的遊樂場-補充 localstorage
系列文
用Canvas打造自己的遊樂場30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言